package com.jp.refreshlocalcacheserver.net.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.net.InetSocketAddress;

/**
 * @Author: jipeng
 * @Description: 服务端
 * @Date: Created in 2020/5/12 14:28
 */
@Service
@EnableScheduling
@ConditionalOnProperty(name = {"refres.local.cache.server.port"})
public class EchoServer{
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    //通过配置，没有配置给默认值
    @Value("${refres.local.cache.server.port}")
    private int port;

    /**
     * 标记服务在启动
     */
    private boolean serverIsStart = false;

    public ChannelFuture start() throws Exception {
        NioEventLoopGroup group = new NioEventLoopGroup(2);
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(group)
                    .channel(NioServerSocketChannel.class)
                    .localAddress(new InetSocketAddress(port))
                    .childHandler(new EchoServerHandlerInitializer());

            ChannelFuture cf = b.bind().sync();

            logger.info("EchoServer stared and listen on {}" , cf.channel().localAddress());

            //设置服务已启动
            clientStart();
            return cf.channel().closeFuture().sync();
        }finally {
            logger.info("EchoServer close" );
            group.shutdownGracefully().sync();
        }
    }


    /**
     *  1分钟执行一次，防止服务端停止后恢复
     */
    @Scheduled(fixedDelay = 60000)
    public void loopExecute(){
        //服务启动状态不执行后续逻辑
        if(serverIsStart){
            return;
        }

        try{
            start().addListener((f) -> clientStop() );
        }catch (Exception e){
            logger.error("cache server netty start exception, error = > {}", ExceptionUtils.getStackTrace(e));
            clientStop();
        }
    }

    /**
     * 客户端启动
     */
    private void clientStart(){
        serverIsStart = true;
    }

    /**
     * 客户端停止
     */
    private void clientStop(){
        serverIsStart = false;
    }

}
